package com.ykc.helper;

import com.ykc.spring.*;
import com.ykc.utils.ReflectionUtil;

import java.util.*;

public class BeanHelper {

    /**
     * BEAN_MAP相当于一个bean容器, 拥有项目所有bean的实例
     */
    private static final Map<String, List<Object>> BEAN_MAP = new HashMap<String, List<Object>>();

    static {
        //获取所有Component与Service的Bean
        Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
        //将bean实例化, 并放入bean容器中

        createBeanDefinitionMap(beanClassSet);

        for (Class<?> beanClass : beanClassSet) {
            if (!beanClass.isInterface()) {
                String beanName="";
                if (beanClass.isAnnotationPresent(Component.class)){
                    Component annotation=beanClass.getAnnotation(Component.class);
                    beanName=annotation.value();
                }else if (beanClass.isAnnotationPresent(Service.class)){
                    Service annotation=beanClass.getAnnotation(Service.class);
                    beanName=annotation.value();
                }else if (beanClass.isAnnotationPresent(Controller.class)){
                    Controller annotation=beanClass.getAnnotation(Controller.class);
                    beanName=annotation.value();
                }
                Object obj = ReflectionUtil.newInstance(beanClass);
                List<Object> clsInfo=BEAN_MAP.get(beanName);
                clsInfo.add(obj);
                BEAN_MAP.put(beanName, clsInfo);
            }
        }
    }

    /**
     * 获取 Bean 容器
     */
    public static Map<String, List<Object>> getBeanMap() {
        return BEAN_MAP;
    }

    /**
     * 获取 Bean 实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String clsName) {
        if (!BEAN_MAP.containsKey(clsName)) {
            throw new RuntimeException("can not get bean by class: " + clsName);
        }
        //如果是单例bean
//        if (((BeanDefinition)BEAN_MAP.get(clsName)).getScope().equals("singleton")){
//            T res=(T)BEAN_MAP.get(clsName).get(1);
//        }else{
//            //1.实例化
//            Class<?> beanClass=beanDefinition.getBeanClass();
//            Object instance;
//            //实例化bean
//            instance=beanClass.getDeclaredConstructor().newInstance();
//            //2.属性填充/依赖注入
//            //Field即字段即类中的成员变量
//            //getFields()：获得某个类的所有的公共（public）的字段，包括父类中的字段。
//            //getDeclaredFields()获得某个类的所有声明的字段，即包括public、private和proteced
//            Field[] fields=beanClass.getDeclaredFields();
//            for (Field field:fields){
//                //如果该字段采用Autowired注入
//                if (field.isAnnotationPresent(AutoWired.class)){
//                    String fieldName=field.getName();
//                    Object o=getBean(fieldName);
//                    //开启field的set模式
//                    field.setAccessible(true);
//                    //将bean的field字段设置为o
//                    field.set(instance,o);
//                }
//            }
//        }
        T res=(T)BEAN_MAP.get(clsName).get(1);
        return res;
    }


    public static <T> T getBean(Class<?> cls) {
        String clsName="";
        for (Map.Entry<String,List<Object>> entry:BEAN_MAP.entrySet()){
            BeanDefinition beanDefinition=(BeanDefinition)entry.getValue().get(0);
            if (beanDefinition.getBeanClass().equals(cls)){
                clsName=entry.getKey();
                break;
            }
        }


        if (!BEAN_MAP.containsKey(clsName)) {
            throw new RuntimeException("can not get bean by class: " + clsName);
        }
        return (T)BEAN_MAP.get(clsName).get(1);
    }

    /**
     * 设置 Bean 实例
     */
    public static void setBean(Class<?> targetClass, Object obj) {
        BeanDefinition beanDefinition=null;
        String beanName="";
        for (Map.Entry<String,List<Object>> entry:BEAN_MAP.entrySet()){
            List<Object> clsInfo=entry.getValue();
            if (targetClass.equals(((BeanDefinition)clsInfo.get(0)).getBeanClass())){
                beanName=entry.getKey();
                beanDefinition=(BeanDefinition) clsInfo.get(0);
            }
        }
        List<Object> clsPkg=BEAN_MAP.get(beanName);
        clsPkg.remove(1);
        clsPkg.add(obj);
        BEAN_MAP.put(beanName, clsPkg);
    }

    public static void createBeanDefinitionMap(Set<Class<?>> classSet){
        //将所有beanDefinition实例化并放入容器
        for (Class<?> beanClass:classSet) {
            String beanName="";
            if (beanClass.isAnnotationPresent(Component.class)){
                Component annotation=beanClass.getAnnotation(Component.class);
                beanName=annotation.value();
            }else if (beanClass.isAnnotationPresent(Service.class)){
                Service annotation=beanClass.getAnnotation(Service.class);
                beanName=annotation.value();
            }else if (beanClass.isAnnotationPresent(Controller.class)){
                Controller annotation=beanClass.getAnnotation(Controller.class);
                beanName=annotation.value();
            }

            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setBeanClass(beanClass);
            //如果clazz是被Scope注解的类
            if (beanClass.isAnnotationPresent(Scope.class)) {
                //获取clazz上Scope的注解信息，获取bean的作用范围Scope
                Scope scopeAnnotation = beanClass.getAnnotation(Scope.class);
                beanDefinition.setScope(scopeAnnotation.value());
            } else {
                //单例
                beanDefinition.setScope("singleton");
            }
            List<Object> clsInfo=new ArrayList<>();
            clsInfo.add(beanDefinition);
            BEAN_MAP.put(beanName,clsInfo);
        }
    }

}
